package com.example.capsule.service;

import com.example.capsule.entity.Capsule;
import com.example.capsule.entity.Invitation;
import com.example.capsule.entity.User;
import com.example.capsule.repository.CapsuleRepository;
import com.example.capsule.repository.InvitationRepository;
import com.example.capsule.repository.UserRepository;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 时光胶囊服务
 */
@Service
@Transactional
public class CapsuleService {

    private final CapsuleRepository capsuleRepository;
    private final FileStorageService fileStorageService;
    private final InvitationService invitationService;
    private final InvitationRepository invitationRepository;
    private final UserRepository userRepository;
    private final String baseUrl;
    // 移除SmsService依赖，使用mock方式
    // private final SmsService smsService;

    public CapsuleService(CapsuleRepository capsuleRepository,
                          FileStorageService fileStorageService,
                          InvitationService invitationService,
                          InvitationRepository invitationRepository, UserRepository userRepository, @Value("${app.base-url}") String baseUrl) {
        this.capsuleRepository = capsuleRepository;
        this.fileStorageService = fileStorageService;
        this.invitationService = invitationService;
        this.invitationRepository = invitationRepository;
        this.userRepository = userRepository;
        // this.smsService = smsService;
        this.baseUrl = baseUrl;
    }

    /**
     * 创建时光胶囊
     */
    public Capsule createCapsule(Capsule capsule, MultipartFile imageFile) throws IOException {
        // 如果有图片文件，保存图片
        if (imageFile != null && !imageFile.isEmpty()) {
            String fileName = fileStorageService.storeFile(imageFile);
            capsule.setImagePath(fileName);
        }

        return capsuleRepository.save(capsule);
    }

    public Capsule createCapsuleWithInvitation(Capsule capsule, MultipartFile imageFile,
                                               String senderPhone, String recipientPhone) throws IOException {
        // 设置发送者
        capsule.setSenderPhone(senderPhone);
        // 如果有接收人手机号，设置为接收人
        if (recipientPhone != null && !recipientPhone.trim().isEmpty()) {
            capsule.setRecipientPhone(recipientPhone);
            // 设置通知未发送状态
            capsule.setNotificationSent(false);
        }
        // 保存胶囊
        Capsule savedCapsule = createCapsule(capsule, imageFile);

        // 如果有接收人手机号，创建邀请（但不发送短信）
        if (recipientPhone != null && !recipientPhone.trim().isEmpty()) {
            // 只创建邀请记录，不发送短信
            createInvitationWithoutSms(savedCapsule.getId(), senderPhone, recipientPhone);
            System.out.println("邀请已创建，短信将在解锁时发送");
        }
        return savedCapsule;
    }

    // 新增方法：创建邀请但不发送短信
    private void createInvitationWithoutSms(Long capsuleId, String senderPhone, String recipientPhone) {
        try {
            Invitation invitation = new Invitation();
            invitation.setCapsuleId(capsuleId);
            invitation.setRecipientPhone(recipientPhone);
            invitation.setInviteToken(generateInviteToken());
            invitation.setStatus("PENDING");
            invitation.setCreatedAt(LocalDateTime.now());
            invitation.setExpiresAt(LocalDateTime.now().plusDays(7));

            invitationRepository.save(invitation);
            System.out.println("邀请记录已保存（不发送短信）");

        } catch (Exception e) {
            System.err.println("创建邀请记录失败: " + e.getMessage());
        }
    }

    // 生成邀请令牌的辅助方法
    private String generateInviteToken() {
        return UUID.randomUUID().toString().replace("-", "");
    }

    @Scheduled(fixedRate = 60000)
    public void checkAndUnlockCapsules() {
        List<Capsule> expiredCapsules = capsuleRepository.findExpiredCapsules(LocalDateTime.now());
        for (Capsule capsule : expiredCapsules) {
            // 标记为已解锁
            capsule.setIsUnlocked(true);

            // 如果有接收人且未发送过通知，发送解锁短信（包含邀请链接）
            if (capsule.getRecipientPhone() != null &&
                    !capsule.getRecipientPhone().trim().isEmpty() &&
                    !Boolean.TRUE.equals(capsule.getNotificationSent())) {

                sendUnlockNotificationWithInvitation(capsule); // 发送包含邀请链接的解锁通知
                capsule.setNotificationSent(true);
            }

            capsuleRepository.save(capsule);
            System.out.println("胶囊解锁: ID=" + capsule.getId() +
                    ", 标题=" + capsule.getTitle() +
                    ", 解锁时间=" + LocalDateTime.now());
        }
        if (!expiredCapsules.isEmpty()) {
            System.out.println("解锁了 " + expiredCapsules.size() + " 个胶囊");
        }
    }

    // 新增方法：发送包含邀请链接的解锁通知
    private void sendUnlockNotificationWithInvitation(Capsule capsule) {
        try {
            // 获取或创建邀请令牌
            String inviteToken = getOrCreateInvitationToken(capsule.getId(), capsule.getRecipientPhone());
            String inviteUrl = "https://expensive-monroe-moms-revenues.trycloudflare.com/invitation?token=" + inviteToken;

            String senderName = getSenderName(capsule.getSenderPhone());
            String capsuleTitle = capsule.getTitle() != null ? capsule.getTitle() : "未命名";

            String message = String.format(
                    "【时光胶囊】%s发给您的时光胶囊《%s》已解锁！点击链接查看：%s",
                    senderName, capsuleTitle, inviteUrl
            );

            System.out.println("=== 解锁邀请短信 ===");
            System.out.println("收件人: " + capsule.getRecipientPhone());
            System.out.println("内容: " + message);
            System.out.println("==================");

            // TODO: 如果需要实际发送短信，取消注释下面的代码
            // smsService.sendCustomSms(capsule.getRecipientPhone(), message);

        } catch (Exception e) {
            System.err.println("发送解锁邀请通知失败: " + e.getMessage());
        }
    }

    // 获取或创建邀请令牌
    private String getOrCreateInvitationToken(Long capsuleId, String recipientPhone) {
        try {
            // 先查找是否已有邀请记录
            Optional<Invitation> existingInvitation = invitationRepository
                    .findByCapsuleIdAndRecipientPhone(capsuleId, recipientPhone);

            if (existingInvitation.isPresent()) {
                return existingInvitation.get().getInviteToken();
            }

            // 如果没有找到，创建新的邀请记录
            Invitation newInvitation = new Invitation();
            newInvitation.setCapsuleId(capsuleId);
            newInvitation.setRecipientPhone(recipientPhone);
            newInvitation.setInviteToken(generateInviteToken());
            newInvitation.setStatus("PENDING");
            newInvitation.setCreatedAt(LocalDateTime.now());
            newInvitation.setExpiresAt(LocalDateTime.now().plusDays(7));

            invitationRepository.save(newInvitation);
            return newInvitation.getInviteToken();

        } catch (Exception e) {
            System.err.println("获取或创建邀请令牌失败: " + e.getMessage());
            return "error-token"; //  fallback
        }
    }

    // 获取发送者名称
    private String getSenderName(String senderPhone) {
        try {
            Optional<User> user = userRepository.findByPhone(senderPhone);
            return user.map(User::getNickname).orElse(senderPhone);
        } catch (Exception e) {
            return senderPhone;
        }
    }

    /**
     * Mock方式发送解锁通知短信
     * TODO: 后续需要替换为真实短信服务
     */
    private void sendUnlockNotificationMock(Capsule capsule) {
        try {
            String message = String.format(
                    "【时光胶囊】%s发给您的时光胶囊'%s'已解锁，请登录查看内容。",
                    capsule.getSenderPhone(),
                    capsule.getTitle() != null ? capsule.getTitle() : "未命名"
            );

            // Mock短信发送 - 仅打印到控制台
            System.out.println("=== MOCK短信发送 ===");
            System.out.println("收件人: " + capsule.getRecipientPhone());
            System.out.println("内容: " + message);
            System.out.println("=== MOCK短信结束 ===");

            // TODO: 生产环境需要替换为真实短信发送
            // smsService.sendSms(capsule.getRecipientPhone(), message);

        } catch (Exception e) {
            System.err.println("发送解锁通知失败: " + e.getMessage());
            // 生产环境可能需要重试机制
        }
    }

    /**
     * 获取用户创建的胶囊
     */
    public List<Capsule> getUserCreatedCapsules(String phone) {
        return capsuleRepository.findBySenderPhoneOrderByCreatedAtDesc(phone);
    }

    /**
     * 获取用户收到的胶囊
     */
    public List<Capsule> getUserReceivedCapsules(String phone) {
        return capsuleRepository.findByRecipientPhoneOrderByCreatedAtDesc(phone);
    }

    /**
     * 获取公开的胶囊
     */
    public List<Capsule> getPublicCapsules() {
        return capsuleRepository.findByIsPublicTrueAndIsUnlockedTrueOrderByCreatedAtDesc();
    }

    /**
     * 获取所有已解锁的胶囊（包括公开的和用户有权限查看的）
     */
    public List<Capsule> getAllUnlockedCapsules(String userPhone) {
        List<Capsule> publicCapsules = capsuleRepository.findByIsPublicTrueAndIsUnlockedTrue();
        List<Capsule> userCapsules = capsuleRepository.findBySenderPhoneAndIsUnlockedTrue(userPhone);
        List<Capsule> receivedCapsules = capsuleRepository.findByRecipientPhoneAndIsUnlockedTrue(userPhone);

        // 合并列表并去重
        return Stream.concat(Stream.concat(publicCapsules.stream(), userCapsules.stream()), receivedCapsules.stream())
                .distinct()
                .sorted((c1, c2) -> c2.getCreatedAt().compareTo(c1.getCreatedAt()))
                .collect(Collectors.toList());
    }

    /**
     * 根据ID获取胶囊（带权限验证）
     */
    public Optional<Capsule> getCapsuleById(Long id, String userPhone) {
        Optional<Capsule> capsuleOptional = capsuleRepository.findById(id);

        if (capsuleOptional.isPresent()) {
            Capsule capsule = capsuleOptional.get();

            // 检查用户是否有权限查看
            if (capsule.canView(userPhone)) {
                return capsuleOptional;
            }
        }

        return Optional.empty();
    }

    /**
     * 检查胶囊是否可以查看（权限验证）
     */
    public boolean canViewCapsule(Long id, String userPhone) {
        Optional<Capsule> capsuleOptional = capsuleRepository.findById(id);
        return capsuleOptional.map(capsule -> capsule.canView(userPhone)).orElse(false);
    }

    /**
     * 删除胶囊（带权限验证）
     */
    public boolean deleteCapsule(Long id, String userPhone) throws IOException {
        Optional<Capsule> capsuleOptional = capsuleRepository.findById(id);

        if (capsuleOptional.isPresent()) {
            Capsule capsule = capsuleOptional.get();

            // 只有发送者可以删除胶囊
            if (!capsule.getSenderPhone().equals(userPhone)) {
                return false;
            }

            // 删除关联的图片文件
            if (capsule.getImagePath() != null && !capsule.getImagePath().isEmpty()) {
                fileStorageService.deleteFile(capsule.getImagePath());
            }

            capsuleRepository.deleteById(id);
            return true;
        }

        return false;
    }

    /**
     * 更新胶囊公开状态 - 确认此方法存在
     */
    public boolean updateCapsuleVisibility(Long id, String userPhone, boolean isPublic) {
        Optional<Capsule> capsuleOptional = capsuleRepository.findById(id);

        if (capsuleOptional.isPresent()) {
            Capsule capsule = capsuleOptional.get();

            // 只有发送者可以修改公开状态
            if (!capsule.getSenderPhone().equals(userPhone)) {
                return false;
            }

            capsule.setIsPublic(isPublic);
            capsuleRepository.save(capsule);
            return true;
        }

        return false;
    }

    /**
     * 获取用户的所有胶囊统计
     */
    public CapsuleStats getUserCapsuleStats(String phone) {
        long createdCount = capsuleRepository.countBySenderPhone(phone);
        long receivedCount = capsuleRepository.countByRecipientPhone(phone);
        long unlockedCount = capsuleRepository.countBySenderPhoneAndIsUnlockedTrue(phone) +
                capsuleRepository.countByRecipientPhoneAndIsUnlockedTrue(phone);
        long lockedCount = capsuleRepository.countBySenderPhoneAndIsUnlockedFalse(phone) +
                capsuleRepository.countByRecipientPhoneAndIsUnlockedFalse(phone);

        return new CapsuleStats(createdCount, receivedCount, unlockedCount, lockedCount);
    }

    /**
     * 获取所有胶囊（管理用）
     */
    public List<Capsule> findAllCapsules() {
        return capsuleRepository.findAll();
    }



    /**
     * 搜索用户的胶囊
     */
    public List<Capsule> searchUserCapsules(String phone, String keyword) {
        return capsuleRepository.findBySenderPhoneAndTitleContainingOrContentContaining(
                phone, keyword, keyword);
    }



    /**
     * 文件清理任务
     */
    @Scheduled(cron = "0 0 2 * * ?") // 每天凌晨2点执行
    public void cleanupOldFiles() {
        try {
            fileStorageService.cleanupOldFiles(Duration.ofDays(7)); // 清理7天前的文件
            System.out.println("文件清理任务执行完成");
        } catch (IOException e) {
            System.err.println("文件清理失败: " + e.getMessage());
        }
    }

    /**
     * 获取基础URL
     */
    public String getBaseUrl() {
        return baseUrl;
    }

    /**
     * 胶囊统计类
     */
    public static class CapsuleStats {
        private final long createdCount;
        private final long receivedCount;
        private final long unlockedCount;
        private final long lockedCount;

        public CapsuleStats(long createdCount, long receivedCount, long unlockedCount, long lockedCount) {
            this.createdCount = createdCount;
            this.receivedCount = receivedCount;
            this.unlockedCount = unlockedCount;
            this.lockedCount = lockedCount;
        }

        // Getters
        public long getCreatedCount() { return createdCount; }
        public long getReceivedCount() { return receivedCount; }
        public long getUnlockedCount() { return unlockedCount; }
        public long getLockedCount() { return lockedCount; }
        public long getTotalCount() { return createdCount + receivedCount; }
    }
}